import * as vscode from 'vscode';

export default class Lua2Ts{ 
    context : vscode.ExtensionContext = null;
    disposable : vscode.Disposable = null;

    constructor(context : vscode.ExtensionContext){
        this.context = context;
    }
    
    registerCommand(){
        //注册事件
        this.disposable = vscode.commands.registerTextEditorCommand('zhaoExtensionTools.LUA2TsStruct', (textEditor, edit) => {
            const doc = textEditor.document;
            let selection: vscode.Selection | vscode.Range = textEditor.selection;
            
            let text = doc.getText(selection);
            if (text === "") {
                vscode.window.showInformationMessage("未选择文本");
                return;
            }
            //替换文件内容
            const replaceStr = this.lua2TsStruct(text);
            if (replaceStr === "") {
                vscode.window.showErrorMessage("转换失败，请注意格式");
                return;
            }
            textEditor.edit((builder) => {
                builder.replace(selection, replaceStr);
            });
        });
        this.context.subscriptions.push(this.disposable);
    }
    unRegisterCommand(){

    }


    //注释
    processNotation(index : {startIndex : number}, txt : string){
        let startReg = /^(?:\s*--\s*(.+)\s*\n?)/g;                   //开始的注释
        startReg.lastIndex = index.startIndex;
        let startArray = startReg.exec(txt);
        index.startIndex = startReg.lastIndex;
        return startArray;
    }

    //结构体名
    processStructName(index : {startIndex : number}, txt : string){
        let reg = /\s*\S+\.(\S+)\s*=\sclass\(.+\)\r*\n\s*function\s.+\s*?\n?/g;
        reg.lastIndex = index.startIndex;
        let startArray = reg.exec(txt);
        index.startIndex = reg.lastIndex;
        return startArray;
    }
    
    //命令号 CMDExt.SUB_CM_MATCH_JOININ                            = 1                 --加入比赛
    processCommand(index : {startIndex : number}, txt : string) : Array<any>{
        let reg = /\s*CMDExt\.(.\S*)\s*=\s*(\d+)\s*(?:--\s*(.*))?\s*?\n?/g;
        reg.lastIndex = index.startIndex;
        let contentArray = [];
        let tempArray = null;
        while((tempArray = reg.exec(txt)) !== null)
        {
            contentArray.push(tempArray);
            index.startIndex = reg.lastIndex;
        }
        return contentArray;
    }
    
    //结构体内容
    processContentStringRead(index : {startIndex : number}, txt : string) : Array<any>{
        let reg = /\s*self\.(.\S*)\s*=\s*ba:read(.*)\((.*)\)\s*(?:--\s*(.*))?\s*?\n?/g;
        reg.lastIndex = index.startIndex;
        let contentArray = [];
        let tempArray = null;
        while((tempArray = reg.exec(txt)) !== null)
        {
            const arr = [tempArray[1], tempArray[2], tempArray[3], tempArray[4]];
            contentArray.push(arr);
            index.startIndex = reg.lastIndex;
        }
        return contentArray;
    }

    //结构体内容
    processContentStringWrite(index : {startIndex : number}, txt : string) : Array<any>{
        let reg = /\s*ba:write(\w*)\(\s*self\.(\w+)(?:\s*,\s*([\w\.]*))?\s*\)\s*(?:--\s*(.+))?\s*?\n?/g;
        reg.lastIndex = index.startIndex;
        let contentArray = [];
        let tempArray = null;
        while((tempArray = reg.exec(txt)) !== null)
        {
            // 名字，类型，长度，注释 排序
            const arr = [tempArray[2], tempArray[1], tempArray[3], tempArray[4]];
            contentArray.push(arr);
            index.startIndex = reg.lastIndex;
        }
        return contentArray;
    }

    //结构体结束符};
    processEndString(index : {startIndex : number}, txt : string){
        let endReg = /\s*end\s*?\n?/g;
        endReg.lastIndex = index.startIndex;
        let endArray = endReg.exec(txt);
        return endArray;
    }

    lua2TsStruct(txt : string) : string{
        let startIndex = {startIndex : 0};
        let resultStr : string = "";
        let commandArray = this.processCommand(startIndex, txt);
        let headArray = this.processNotation(startIndex, txt);
        let structNameArray = this.processStructName(startIndex, txt);
        let contentArray = this.processContentStringWrite(startIndex, txt);
        if (contentArray.length === 0) {
            contentArray = this.processContentStringRead(startIndex, txt);
        }
        let endArray = this.processEndString(startIndex, txt);

        if (commandArray) {
            let lineStr: string = "";
            for (const array_ of commandArray) {
                if (array_[3]) {
                    lineStr += `/** ${array_[3]} */\n`;
                }
                lineStr += `export const ${array_[1]}: number = ${array_[2]}\n`;
            }
            resultStr += lineStr;
        }
        if (headArray) {        //有头部
            if (headArray[1]) {     //有注释
                resultStr += "/** " + headArray[1] + "*/\n";
            }
        }
        if (structNameArray) {        //有头部
            if (structNameArray[1]) {     //有注释
                resultStr += `export class ${structNameArray[1]} extends Struct {\n`;
            }
        }

        const numName: string[] = ["BYTE", "WORD", "DWORD", "LONGLONG", "Int", "SCORE"];
        let lineStr: string = "";
        for (const array_ of contentArray) {
            if (array_[3]) {
                lineStr += `\t/** ${array_[3]} */\n`;
            }
            if (numName.indexOf(array_[1]) !== -1) {
                lineStr += "\t" + array_[0];
                lineStr += ": number = 0\n";
            } else if (array_[1] === "Double") {
                let name: string = "";
                if (array_[0].startsWith("l")) {
                    name = (array_[0] as string).replace(/^(?:l)(.+)/, "d$1");
                } else if (array_[0].startsWith("d")) {
                    name = array_[0];
                } else {
                    name = "d" + array_[0];
                }
                lineStr += "\t" + name;
                lineStr += ": number = 0\n";
            }else if (array_[1] === "Bool") {
                lineStr += "\t" + array_[0];
                lineStr += ": boolean = false\n";
            } else if (array_[1] === "CHAR" || array_[1] === "TCHAR") {
                let name: string = "";
                if (array_[1] === "CHAR") {
                    if (array_[0].startsWith("sz")) {
                        name = (array_[0] as string).replace(/^(?:sz)(.+)/, "c$1");
                    } else if (array_[0].startsWith("c")) {
                        name = array_[0];
                    } else {
                        name = "c" + array_[0];
                    }
                } else {
                    if (array_[0].startsWith("sz")) {
                        name = array_[0];
                    } else {
                        name = "sz" + array_[0];
                    }
                }
                if (parseInt(array_[2])) {
                    lineStr += "\t" + `${name}_${array_[2]}_`;
                } else {
                    lineStr += "\t" + `@${name}_长度_`;

                }
                lineStr += ": string = \"\"\n";
            } else {
                lineStr += "\t" + array_[0];
                lineStr += ": unknow = 0\n";
            }
        }
        resultStr += lineStr;
        if (endArray) {
            resultStr += "}";
        }
        return resultStr;
    }
}